//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __ABC_H_
#define __ABC_H_
/*
 * abc.h  Definitions for the Asynchronous Buffer Cache
 */
#include <tfssys.h>
typedef unsigned long daddr_t;

#define NCACHE ( 2048 ) // 1MB

/*
 * Sector size, and log2(size)
 */
#define EXTSIZ (128)

/*
 * Flags to find_buf()
 */
#define ABC_FILL (0x01)        /* Fill from disk? */
#define ABC_BG (0x02)          /* Fill in background? */

/*
 * Operations
 */
#define Q_IDLE (0)            /* Flag that op is complete */
#define Q_FILLBUF (1)         /* Fill buffer */
#define Q_FLUSHBUF (2)        /* Write buffer out */

/*
 * Bits in b_flags
 */
#define B_SEC0 0x1        /* 1st sector valid  */
#define B_SECS 0x2        /*  ...rest of sectors valid too */
#define B_DIRTY 0x4       /* Some sector in buffer is dirty */

/*
 * Description of a particular buffer of data
 */
struct buf
{
    IMutex *b_lock; /* CriticalSection for FG/BG data structures */
    struct llist *b_list;    /* Linked under bufhead */
    void *b_data;            /* Actual data */
    daddr_t b_start;         /* Starting sector # */
    UInt32 b_nsec;             /*  ...# SECSZ units contained */
    volatile UInt32 b_flags;   /* Flags */
    volatile UInt32 b_locks;   /* Count of locks on buf */
    void **b_handles;        /* Tags associated with B_DIRTY */
    UInt32 b_nhandle;          /*  ...# pointed to */
};
class BufCache;
class fatfs_sharedata;
class abc
{
public:
    struct buf *find_buf(daddr_t d, UInt32 nsec, int flags);
    void * index_buf(struct buf *b, UInt32 index, UInt32 nsec);
    void init_buf(void *pDevice, fatfs_sharedata* pData);
    void dirty_buf(struct buf *b, void *handle);
    void lock_buf(struct buf *b);
    void unlock_buf(struct buf *b);
    void sync_bufs(void *handle);
    bool sync_one_block();
    void abc_clearbuf(void);
    Boolean exec_qio(struct buf *b, int op);
    void setBufCache(BufCache *pCache);
#if defined(_DEBUG)
    void abc_bufs_stat(UInt32 *Data_secs, UInt32 *Cache_secs);
#endif
    abc();
    ~abc();
    UInt32  AddRef(void);
    UInt32  Release(void);

private:
    //void (struct buf *b);
    int read_secs(daddr_t start, unsigned char *buf, UInt32 nsec);
    int write_secs(daddr_t start, unsigned char *buf, UInt32  nsec);
    void free_buf(struct buf *b);
    int age_buf(void);
    int _sync_buf(struct buf *b, int from_qio);
    UInt32 stob(UInt32 nsec);

   // UInt32 qnext;               /* Next position in ring */
    UInt32 bufsize;             /* # sectors held in memory currently */
    struct hash *bufpool;     /* Hash daddr_t -> buf */
    struct llist allbufs;     /* Time-ordered list, for aging */
    BufCache *pBufCache;
    IMutex *allbufs_lock;
    PDevDriver pBlkDev;
    UInt32 m_nRef;
    fatfs_sharedata* p_Sharedata;
};

#endif /* __ABC_H_ */
